A Non-Coders Guide to Adwords Scripts - Point It · 2016-04-19 · #PI_Scripts #AdWordsScripts...

Preview:

Citation preview

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

A Non-Coders Guide to Adwords ScriptsIt’s not as intimidating as you thought!

Point It Digital Marketingwww.Pointit.com 06.17.2015

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

Housekeeping Slide

Additional Q&A addressed and at the end of session

A link to view a recorded version of the webinar will be emailed within 48 hours

Raise your hand if you are having technical difficulties

Hide the chat window

Submit question via chat

Toolbox Blog on the Point It Website

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

#PI_Scripts#AdWordsScripts

@ChristiJOlson @SamuelDJames

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

About Point It

Our Clients

Our Services

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

Today’s Presenters

5

Christi OlsonPoint It Digital MarketingDirector of SEM

Samuel D. JamesPoint It Digital MarketingDirector of Analytics

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STRUCTURE BASIC CONCEPTSREADING SCRIPTSEDITING SCRIPTS

WHAT WE’LL BE TALKING ABOUT TODAY:

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

IS LIKE LEARNING A NEW LANGUAGE…

STRUCTURE TERMINOLOGY

BASIC RULES

PRACTICE MAKES PERFECT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SCRIPTS ENABLE YOU TO AUTOMATE ALL THE THINGS

THAT CAN BE DONE MANUALLY IN ADWORDS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SCRIPTS CANMAKE CHANGES TO OR REPORT ON

ANY ELEMENT OF AN ADWORDS ACCOUNT.

ACCOUNT OR MCC LEVEL

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

ANYTHING YOU CAN DO SCRIPTS CAN DO TOO

“Annie Get Your Gun”

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SO WHY ARE SO MANY MARKETERS INTIMIDATED

BY SCRIPTS?

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

THEUNKNOWN

IS JAVASCRIPT.

IT’S NOT PART OF THE AVERAGE SEM SKILL SET.

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

LET'S START WITH

STRUCTURE

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

I LIKE COOKING MY FAMILY AND PETS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

I LIKE COOKING, MY FAMILY, AND PETS.

USE PROPER STYLE [PUNCTUATION]THE LIVES IT SAVES MIGHT BE YOUR FAMILY'S

Google JavaScript Coding Style Guide:

bit.ly/GoogleJavaScript

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

NOTEPAD++ bit.ly/Notepad-plusplus

• OUTLINES CODE

• MAKES IT EASIER TO SEE WHAT YOU ARE DOING

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SCRIPTS ARE CASE SENSITIVE AND

NEED TO BE WRITTEN IN camelCase

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

// IS A SINGLE COMMENT LINE

// comments can start anywhere in a line and javascript will skip to the end of the line// add as many or as few comments to your code explaining what it does

(DOUBLE SLASH)

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

/* SINGLE FORWARD SLASH + ASTERISK

(SLASH)

*Signifies comments that span multiple*lines. *Multiline comments end with */

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

ALWAYS PREVIEW

A SCRIPT BEFORE YOU RUN IT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts@ChristiJOlson @SamuelDJames

LET'S MOVE TO THE

BASIC CONCEPTS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

THE KEY ITEMS YOU NEED TO KNOW:

• FUNCTIONS• OBJECTS (ELEMENTS)• ENTITIES• VARIABLES• METHODS• SELECTORS• ITERATORS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

ANATOMY OF A BASIC SCRIPT

FUNCTION

SELECTORS

ITERATOR + next METHODS

VARIABLE, OBJECT, ENTITY

LOGGER

METHODS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

FUNCTIONS PERFORM TASKS / PROCEDURES

{ } CURLY BRACKETS DEFINE THE BEGINNING & END OF A

FUNCTION

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

OBJECTS -- COLLECTION OF “ENTITIES”

AdWordsApp MccApp

SpreadsheetApp UrlFetchApp

ADWORDSACCOUNT

CONNECTS WITH SPREADSHEETS

(FOR REPORTING)

ACROSS YOUR MCC

COMMUNICATES WITH OTHER SERVICES &

APPLICATIONS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

ENTITIES – ELEMENT OR PROPERTY

List of AdWords Entities:

bit.ly/1aeDxby

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

VARIABLES (VAR) ARE USED TO NAME & STORE DATA WITHIN YOUR SCRIPTS

variables are like a container to store “data”

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

ESTABLISH YOUR OBJECTAND SELECT AN ENTITY TO QUERY

var keywords = AdWordsApp.keywords()

OBJECTNAMED

VARIABLE ENTITY

JOIN AN OBJECT AND ENTITY WITH A PERIOD

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

METHODS ARE HOW SCRIPTS INTERACT WITH OBJECTS

• RETRIEVE INFORMATION ABOUT AN OBJECT (WHAT IT IS)

• ASK AN OBJECT ABOUT ITSELF (WHAT CAMPAIGN A KWD IS IN)

• TELL THE OBJECT TO DO SOMETHING (CHANGE STATUS)

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

EXAMPLES OF METHODS

get()getQualityScore()

setDestinationURL()WHEN SETTING OR SPECIFYING A VALUES ENTER IT BETWEEN THE BRACKETS ()

SOME METHODS REQUIRE VALUES. MOST ARE LEFT BLANK ()

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SELECTORS REFINE THE LIST OF ENTITIES

•withCondition()

•withIds()•forDateRange()•withLimit()•orderBy()

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SELECTORS REFINE THE LIST OF ENTITIES AND CAN ORDER IT

• withCondition()(‘Entity > N’); Greater than(‘Entity <N’); Less than

•forDateRange()forDateRange(‘YESTERDAY’); forDateRange(‘LAST_14_DAYS’);

•orderBy()(‘Entity ASC’); Ascending Order (‘Entity DESC’); Descending Order

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

ITERATORS RETURN THE NEXT ITEM

• ITERATORS ARE LIKE AN ARRAY• PATTERN BASED SEARCH• COME AFTER SELECTORS

hasNext()objectNext()

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

LOGGER OUTPUTS THE DATA TO A PREVIEW PANEL

• HELP TROUBLESHOOT SCRIPTS

• SLOWS PROCESSING TIME• RECOMMEND REMOVING

AFTER DEBUGGING

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

LET'S TIE IT TOGETHER

READING SCRIPTS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

ANATOMY OF A BASIC SCRIPT

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

FUNCTION starts the script

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

VARIABLE named keywordsOBJECT ENTITY

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

SELECTORS find keywords:• Enabled• Descending Order by Impression• Date = Yesterday• First 10 (by impression)

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

METHODS gets keywords

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

ITERATOR + next METHODS

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

LOGGER outputs the data for preview

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

closes out the functioncloses out the iterator

ANATOMY OF A BASIC SCRIPT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

function main() {var keywords = AdWordsApp.keywords().withCondition(“Status = ‘ENABLED’”)

.orderBy("Impressions DESC")

.forDateRange("YESTERDAY")

.withLimit(10)

.get();

Logger.log("10 keywords with most impressions yesterday");while (keywords.hasNext()) {var keyword = keywords.next();Logger.log(keyword.getText() + ": " +

keyword.getStatsFor("YESTERDAY").getImpressions());}

}

ANATOMY OF A BASIC SCRIPT

closes out the function

FUNCTION starts the script

closes out the iterator

SELECTORS find keywords:• Enabled• Descending Order by Impression• Date = Yesterday• First 10 (by impression)

ITERATOR + next METHODS

VARIABLE ties ENTITY & OBJECT together

LOGGER

METHODS gets keywords

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

GET STARTED NOW WITH

PRE-WRITTEN SCRIPTS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

Adwords Developer Script Solutions

bit.ly/ScriptSolutions

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

SCRIPTS YOU CAN USE NOW:

• Campaign & Keyword Performance Report, Written by Russ Savage

• Quality Score Tracker, Written by Martin Roettgerding

• Keyword Performance by QS & Position, Written by Google Developers

• Anomaly Detector, Written by Google Developers

• Broken URL Checker, Written by Google Developers & Russ Savage (FreeAdwordsScripts.com)

• Account Audit, Written by Russ Savage (FreeAdwordsScripts.com)

• Search Query Manager, Written by Marcela De Vivo (Gryffin.com)

Toolbox Blog on the Point It Website

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

RESOURCES AND PEOPLE TO FOLLOW:

Optmyzr.com FreeAdwordsScripts.com

@RussellSavage@SiliconVaelleys@ArmondHammer@BloomArty

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

LET'S GET COMFORTABLE WITH

EDITING SCRIPTS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STARTED W/ KEYWORD PERFORMANCE REPORT

Wanted to add 2 additional data points:• Converted Clicks (CVR, CPA)• Conversion Value (ROAS)

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

EXISTINGS SCRIPT: KWD PERFORMANCE REPORT

bit.ly/GG-QSkwdScript

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

DON’T FORGET TO UPDATE THE EMAIL/URL (VAR)

• RECIPIENT_EMAIL• your email address

• SPREADSHEET_URL• URL for the Google Spreadsheet

// Comma-separated list of recipients. Comment out to not send any emails.var RECIPIENT_EMAIL = 'christio@pointit.com';

// URL of the default spreadsheet template. This should be a copy of http://goo.gl/cULxUXvar SPREADSHEET_URL = 'https://docs.google.com/spreadsheet/ccc?key=abc123#gid=0';

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

GOAL: ADD ADDITIONAL DATA POINTS

Wanted to add 2 additional data points:Converted Clicks (CVR, CPA)• Conversion Value (ROAS)

stats.getConvertedClicks() workedstats.getConversionValue() kept giving me an error

getConversionValue() is not available with statsit has to be pulled via a separate type of report

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

THE OUTPUT WITH CONVERTED CLICKS

Wanted to add 2 additional data points:• Converted Clicks (CVR, CPA)• Conversion Value (ROAS)

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

KEYWORD PERFORMANCE REPORT

Added to the additional columns to Headers

function outputQualityScoreData(sheet) {// Output header rowvar header = ['Quality Score','Num Keywords','Impressions','Clicks','CTR (%)','Cost','ConvertedClicks',

];sheet.getRange(3, 2, 1, 7).setValues([header]);

This is an ARRAY In this context it let you update specific data within a spreadsheet. You’re telling it where!getRange = (row to start on,

column to start on, number of rows to include,number of columns to include)

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

KEYWORD PERFORMANCE REPORT

Added to the additional columns to Headers

function outputQualityScoreData(sheet) {// Output header rowvar header = ['Quality Score','Num Keywords','Impressions','Clicks','CTR (%)','Cost','ConvertedClicks',

];sheet.getRange(3, 2, 1, 7).setValues([header]);

I added 1 columnsIncrease # of columns from 6 to 7

Check for multiple instances of arrays within the script!

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

KEYWORD PERFORMANCE REPORT

Added to the additional getStats()

// Compute datavar keywordIterator = AdWordsApp.keywords()

.forDateRange('LAST_WEEK')

.withCondition('Impressions > 0')

.get();while (keywordIterator.hasNext()) {var keyword = keywordIterator.next();var stats = keyword.getStatsFor('LAST_WEEK');var data = qualityScoreMap[keyword.getQualityScore()];if (data) {data.numKeywords++;data.totalImpressions += stats.getImpressions();data.totalClicks += stats.getClicks();data.totalCost += stats.getCost();data.totalConvertedClicks =+ stats.getConvertedClicks();

}}

this pulls in the total converted clicks into the column

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

KEYWORD PERFORMANCE REPORT

YAY, it worked!Now I’ve got to figure out how to speed up our account audit

processes!

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

EVENTUALLY I WANT TO AUTOMATE AUDITING

• Account set-up & settings

• SE Linked accounts audit My Business / Local Merchant Center Google Analytics Webmaster Tools

• Conversion tracking audit

• Goals & Events review

• Remarketing Audiences

• Shopping set-up

• Dynamic Search set-up

• Campaign settings & targeting

• Network settings & targeting

• Display settings & targeting

• Day Parting analysis

• Geo Targeting analysis

• Bid-modifier analysis

• Device Targeting analysis

• Ad delivery & rotation settings

• Ad extension audit

• Landing Page audit/analysis

• Campaign architecture

• Quality Score analysis

• Impression share analysis

• Keyword audit

• Negative keyword audit

• Match type audit

• Ad copy audit

• Display / Destination URL audit

• Missed Opportunity audit

• Performance audit

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

I LIKE THE ACCOUNT AUDIT SCRIPT BUT

IT WASN’T THE FORMAT I WANTED

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

I WANTED AN XLS SPREADSHEET

THAT COULD TRACK (AND MONITOR PROGRESS)

FOR ALL CLIENT ACCOUNTS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

BUT FOR NOW… USE THE ACCOUNT AUDIT SCRIPT

AS A FRAMEWORKTO BUILD OUT THE MORE IN-DEPTH

AUDIT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 1: MAPPING OUT WHAT THE SCRIPT DID

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 2: ORGANIZE WHAT DATA WE NEED

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 3: BREAK DOWN THE EXISTING SCRIPT INTO BITE SIZED PIECES

1. Campaign & Ad Group Names2. # of Keywords by Match Type & Negative3. Location Targeting Audit4. Extensions Audit5. Budget Audit

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 4: CREATE REUSABLE PIECES OF CODE

NESTING FUNCTIONS

DECIDE ON THE ORDER OF THE FUNCTIONS AND PULLING DATA

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 4: CREATE REUSABLE PIECES OF CODE

Create Header Rows within Spreadsheet

Start with Campaigns (because ad groups are within campaigns)

For Campaigns:Get Campaign NamesCalculate total KWDs & Negative KWDs

For Ad GroupsGet Ad Group NamesCalculate total KWDs & Negative KWDs

Push everything to the SpreadsheetLog 1 row per Campaign/Ad Group with Totals

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 5: WRITE THE REUSABLE PIECES OF CODE

http://bit.ly/PI-GetCMP http://bit.ly/PI-GetAG

CAMPAIGN ITERATOR AD GROUP ITERATORS

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

bit.ly/PI-SpreadsheetScript

STEP 5: WRITE THE REUSABLE PIECES OF CODE

PREP THE SPREADSHEET

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 5: WRITE/EDIT CODE

GET CAMPAIGN & AD GROUP DATA

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 5: WRITE/EDIT CODE

CREATE & WRITE TO GOOGLE DOC

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

STEP 5: WRITE/EDIT CODE

COUNT KEYWORDS BY MATCH TYPE

This is the original code from the audit doc

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

bit.ly/PI-KWDauditSCRIPT

STEP 6: PUT IT ALL TOGETHER

QA THE FINISHED PRODUCT

@ChristiJOlson @SamuelDJames#PI_Scripts #AdWordsScripts

Questions?

Get in the Game: Social Advertising Video

Platforms

June 24th @ 11:00am

Register atpointit.co/1HjrmrH

A link to view a recorded version of the webinar will be emailed within 48 hours!

NEXT WEBINAR:

G