marketo

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2023 License: MIT Imports: 19 Imported by: 0

README

go-marketo

GoDoc MIT licensed

Inspired by FrenchBen/goketo and derived from SpeakData/minimarketo, go-marketo provides a thin wrapper around Marketo's REST APIs, along with some utility structs for handling responses.

Installation

go get github.com/polytomic/go-marketo

Usage

Basic operations are:

  1. Create a client
  2. Make a http call (Marketo API only supports GET, POST, DELETE) with url string and data in []byte if needed
  3. Check "success" and parse "result" with your struct

First, create a client. In this example, I'm passing configuration through environment variables.

config := marketo.ClientConfig{
    ID:       os.Getenv("MARKETO_ID"),
    Secret:   os.Getenv("MARKETO_SECRET"),
    Endpoint: os.Getenv("MARKETO_URL"), // https://XXX-XXX-XXX.mktorest.com
    Debug:    true,
}
client, err := marketo.NewClient(config)
if err != nil {
    log.Fatal(err)
}

Then, call Marketo supported http calls: GET, POST, or DELETE.

Find a lead

path := "/rest/v1/leads.json?"
v := url.Values{
    "filterType":   {"email"},
    "filterValues": {"tester@example.com"},
    "fields":       {"email"},
}
response, err := client.Get(path + v.Encode())
if err != nil {
    log.Fatal(err)
}
if !response.Success {
    log.Fatal(response.Errors)
}
var leads []marketo.LeadResult
if err = json.Unmarshal(response.Result, &leads); err != nil {
    log.Fatal(err)
}
for _, lead := range leads {
    fmt.Printf("%+v", lead)
}

Create a lead

path := "/rest/v1/leads.json"
type Input struct {
    Email     string `json:"email"`
    FirstName string `json:"firstName"`
    LastName  string `json:"lastName"`
}
type CreateData struct {
    Action      string  `json:"action"`
    LookupField string  `json:"lookupField"`
    Input       []Input `json:"input"`
}
data := CreateData{
    "createOnly",
    "email",
    []Input{
        Input{"tester@example.com", "John", "Doe"},
    },
}

dataInBytes, err := json.Marshal(data)
response, err := client.Post(path, dataInBytes)
if err != nil {
    log.Fatal(err)
}
if !response.Success {
    log.Fatal(response.Errors)
}
var createResults []marketo.RecordResult
if err = json.Unmarshal(response.Result, &createResults); err != nil {
    log.Fatal(err)
}
for _, result := range createResults {
    fmt.Printf("%+v", result)
}

JSON Response

go-marketo defines the common Marketo response format. This covers most of the API responses.

type Response struct {
	RequestID     string `json:"requestId"`
	Success       bool   `json:"success"`
	NextPageToken string `json:"nextPageToken,omitempty"`
	MoreResult    bool   `json:"moreResult,omitempty"`
	Errors        []struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"errors,omitempty"`
	Result   json.RawMessage `json:"result,omitempty"`
	Warnings []struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"warning,omitempty"`
}

Your job is to parse "Result".

As for convenience, go-marketo defines two commonly used "result" format.

// Find lead returns "result" in this format
type LeadResult struct {
	ID        int    `json:"id"`
	FirstName string `json:"firstName"`
	LastName  string `json:"lastName"`
	Email     string `json:"email"`
	Created   string `json:"createdAt"`
	Updated   string `json:"updatedAt"`
}

// Create/update lead uses this format
type RecordResult struct {
	ID      int    `json:"id"`
	Status  string `json:"status"`
	Reasons []struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"reasons,omitempty"`
}

License

MIT

Documentation

Index

Constants

View Source
const (
	BatchComplete  = "Complete"
	BatchQueued    = "Queued"
	BatchImporting = "Importing"
	BatchFailed    = "Failed"
)
View Source
const (
	// DefaultTimeout is http client timeout and 60 seconds
	DefaultTimeout = 60
)
View Source
const (
	// MaximumQueryBatchSize is the largest batch size requestable via Marketo's
	// list/query API.
	MaximumQueryBatchSize = 300
)

Variables

View Source
var (
	ErrBadGateway                    = Reason{Code: "502"}
	ErrEmptyAccessToken              = Reason{Code: "600"}
	ErrAccessTokenInvalid            = Reason{Code: "601"}
	ErrAccessTokenExpired            = Reason{Code: "602"}
	ErrAccessDenied                  = Reason{Code: "603"}
	ErrRequestTimeOut                = Reason{Code: "604"}
	ErrMethodUnsupported             = Reason{Code: "605"}
	ErrRateLimitExceeded             = Reason{Code: "606"}
	ErrDailyQuotaReached             = Reason{Code: "607"}
	ErrTemporarilyUnavailable        = Reason{Code: "608"}
	ErrInvalidJSON                   = Reason{Code: "609"}
	ErrNotFound                      = Reason{Code: "610"}
	ErrSystemError                   = Reason{Code: "611"}
	ErrInvalidContentType            = Reason{Code: "612"}
	ErrInvalidMultipart              = Reason{Code: "613"}
	ErrInvalidSubscription           = Reason{Code: "614"}
	ErrConcurrentLimitReached        = Reason{Code: "615"}
	ErrInvalidSubscriptionType       = Reason{Code: "616"}
	ErrCannotBeBlank                 = Reason{Code: "701"}
	ErrNoDataFound                   = Reason{Code: "702"}
	ErrFeatureNotEnabled             = Reason{Code: "703"}
	ErrInvalidDateFormat             = Reason{Code: "704"}
	ErrBusinessRuleViolation         = Reason{Code: "709"}
	ErrParentFolderNotFound          = Reason{Code: "710"}
	ErrIncompatibleFolderType        = Reason{Code: "711"}
	ErrMergeOperationInvalid         = Reason{Code: "712"}
	ErrTransientError                = Reason{Code: "713"}
	ErrUnableToFindDefaultRecordType = Reason{Code: "714"}
	ErrExternalSalesPersonIDNotFound = Reason{Code: "718"}

	ErrTooManyImports = Reason{Code: "1016"}
)
View Source
var (
	Leads = ImportObject{
		// contains filtered or unexported fields
	}
)

Functions

This section is empty.

Types

type AuthToken

type AuthToken struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
	Scope       string `json:"scope"`
}

AuthToken holds data from Auth request

type BatchResult

type BatchResult struct {
	BatchID          int    `json:"batchId"`
	ImportID         string `json:"importId"`
	Status           string `json:"status"`
	LeadsProcessed   int    `json:"numOfLeadsProcessed,omitempty"`
	Failures         int    `json:"numOfRowsFailed"`
	Warnings         int    `json:"numOfRowsWithWarning"`
	Message          string `json:"message"`
	ObjectsProcessed int    `json:"numOfObjectsProcessed,omitempty"`
	ObjectName       string `json:"objectApiName,omitempty"`

	Processed int `json:"-"`
}

BatchResult contains the details of a batch, returned by the Create & Get functions

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client Marketo http Client

func NewClient

func NewClient(config ClientConfig) (*Client, error)

NewClient returns a new Marketo Client

func (*Client) Delete

func (c *Client) Delete(resource string, data []byte) (response *Response, err error)

Delete sends an HTTP DELETE request to specified resource url with given data

func (*Client) Get

func (c *Client) Get(resource string) (response *Response, err error)

Get performs an HTTP GET for the specified resource url

func (*Client) GetTokenInfo

func (c *Client) GetTokenInfo() TokenInfo

GetTokenInfo returns current TokenInfo stored in Client

func (*Client) Post

func (c *Client) Post(resource string, data []byte) (response *Response, err error)

Post performs an HTTP POST to the specified resource url with given data

func (*Client) RefreshToken

func (c *Client) RefreshToken() (auth AuthToken, err error)

RefreshToken refreshes the auth token. This is purely for testing purpose and not intended to be used.

type ClientConfig

type ClientConfig struct {
	// ID: Marketo client ID
	ID string
	// Secret: Marketo client secret
	Secret string
	// Endpoint: https://xxx-xxx-xxx.mktorest.com
	Endpoint string
	// Timeout, optional: default http timeout is 60 seconds
	Timeout uint
	// Debug, optional: a flag to show logging output
	Debug bool
	// AuthTransport, optional: the HTTP RoundTripper to use when
	// making authentication calls to Marketo
	AuthTransport http.RoundTripper
	// RESTTransport, optional: the HTTP RoundTripper to use when
	// making calls to the REST API.
	RESTTransport http.RoundTripper
}

ClientConfig stores client configuration

type CustomObjectMetadata

type CustomObjectMetadata struct {
	IDField          string           `json:"idField"`
	APIName          string           `json:"name"`
	Description      string           `json:"description"`
	DisplayName      string           `json:"displayName"`
	PluralName       string           `json:"pluralName"`
	Fields           []ObjectField    `json:"fields"`
	SearchableFields [][]string       `json:"searchableFields"`
	DedupeFields     []string         `json:"dedupeFields"`
	Relationships    []ObjectRelation `json:"relationships"`
	CreatedAt        time.Time        `json:"createdAt"`
	UpdatedAt        time.Time        `json:"updatedAt"`
	State            ObjectState      `json:"state"`
	Version          ObjectVersion    `json:"version"`
}

type CustomObjectResult

type CustomObjectResult struct {
	MarketoGUID string                 `json:"marketoGUID"`
	Sequence    int                    `json:"seq"`
	Fields      map[string]interface{} `json:"-" mapstructure:",remain"`
}

CustomObjectResult contains a single record returned when filtering custom objects.

type CustomObjects

type CustomObjects struct {
	*Client
}

CustomObjects provides access to the Marketo custom objects API

func NewCustomObjectsAPI

func NewCustomObjectsAPI(c *Client) *CustomObjects

NewCustomObjectsAPI returns a new instance of the

func (*CustomObjects) Describe

func (c *CustomObjects) Describe(ctx context.Context, name string) (*CustomObjectMetadata, error)

Describe returns the description for the provided custom object

func (*CustomObjects) Filter

func (c *CustomObjects) Filter(ctx context.Context, name string, opts ...QueryOption) ([]CustomObjectResult, string, error)

Filter queries Marketo for custom objects that match the provided filters.

func (*CustomObjects) List

List returns the custom objects supported by the Marketo instance

type Error

type Error struct {
	Message    string
	StatusCode int
	Body       string

	Errors []Reason
}

Error contains the error state returned from a Marketo operation

func ErrorForReasons

func ErrorForReasons(status int, reasons ...Reason) Error

ErrorForReasons returns a new Error wrapping the Reasons provided by the Marketo API

func (Error) Error

func (e Error) Error() string

Error fulfills the error interface

func (Error) Is

func (e Error) Is(target error) bool

Is provides support for the errors.Is() call, and will return true if the passed target is a Reason and it matches any of the Reasons included with this Error.

type ImportAPI

type ImportAPI struct {
	*Client
}

ImportAPI provides access to the Marketo import API

func NewImportAPI

func NewImportAPI(c *Client) *ImportAPI

NewImportAPI returns a new instance of the import API, configured using the provided options

func (*ImportAPI) Create

func (i *ImportAPI) Create(ctx context.Context, obj ImportObject, file io.Reader) ([]BatchResult, error)

Create uploads a new file for importing, returning the new asynchronous import

func (*ImportAPI) Failures

func (i *ImportAPI) Failures(ctx context.Context, obj ImportObject, id int) ([]LeadImportFailure, error)

Failures returns the list of failed recrods for an import

func (*ImportAPI) Get

func (i *ImportAPI) Get(ctx context.Context, obj ImportObject, id int) (*BatchResult, error)

Get retrieves an existing import by its batch ID

type ImportObject

type ImportObject struct {
	// contains filtered or unexported fields
}

func ImportObjectForAPIName

func ImportObjectForAPIName(apiName string) ImportObject

ImportObjectForAPIName returns the ImportObject given the API name of a Marketo object

type LeadAPI

type LeadAPI struct {
	// contains filtered or unexported fields
}

LeadAPI provides access to the Marketo Lead API

func NewLeadAPI

func NewLeadAPI(c *Client) *LeadAPI

NewLeadAPI returns a new instance of the lead API, configured with the provided Client.

func (*LeadAPI) DescribeFields

func (l *LeadAPI) DescribeFields(ctx context.Context) ([]LeadAttribute2, error)

DescribeFields fetches the Lead schema from Marketo and returns the set of attributes defined

func (*LeadAPI) Filter

func (l *LeadAPI) Filter(ctx context.Context, opts ...QueryOption) ([]LeadResult, string, error)

Filter queries Marketo for one or more Leads, returning them if present

type LeadAttribute

type LeadAttribute struct {
	DataType    string           `json:"dataType"`
	DisplayName string           `json:"displayName"`
	ID          int              `json:"id"`
	Length      int              `json:"length"`
	REST        LeadAttributeMap `json:"rest"`
	SOAP        LeadAttributeMap `json:"soap"`
}

LeadAttribute is returned by the Describe Leads endpoint

type LeadAttribute2

type LeadAttribute2 struct {
	Name        string `json:"name,omitempty"`
	DisplayName string `json:"displayName,omitempty"`
	DataType    string `json:"dataType,omitempty"`
	Length      int    `json:"length,omitempty"`
	Updateable  bool   `json:"updateable,omitempty"`
	CRMManaged  bool   `json:"crmManaged,omitempty"`

	Searchable bool `json:"searchable,omitempty"`
}

LeadAttribute2 defines a lead attribute defined by the describe2.json endpoint.

type LeadAttributeMap

type LeadAttributeMap struct {
	Name     string `json:"name"`
	ReadOnly bool   `json:"readOnly"`
}

LeadAttributeMap defines the name & readonly state of a Lead Attribute

type LeadImportFailure

type LeadImportFailure struct {
	Reason string
	Fields map[string]interface{}
}

LeadImportFailure contains a single lead record failure, along with the reason for failure.

type LeadResult

type LeadResult struct {
	ID        int    `json:"id" mapstructure:"id"`
	FirstName string `json:"firstName" mapstructure:"firstName"`
	LastName  string `json:"lastName" mapstructure:"lastName"`
	Email     string `json:"email" mapstructure:"email"`
	Created   string `json:"createdAt" mapstructure:"createdAt"`
	Updated   string `json:"updatedAt" mapstructure:"updatedAt"`

	Fields map[string]string `json:"-" mapstructure:",remain"`
}

LeadResult default result struct

type ObjectField

type ObjectField struct {
	DataType    string `json:"dataType"`
	DisplayName string `json:"displayName"`
	Length      int    `json:"length"`
	Name        string `json:"name"`
	Updateable  bool   `json:"updateable"`
	CRMManaged  bool   `json:"crmManaged"`

	Searchable bool `json:"searchable,omitEmpty"`
}

type ObjectRelation

type ObjectRelation struct {
	Field     string        `json:"field"`
	RelatedTo RelatedObject `json:"relatedTo"`
	Type      string        `json:"type"`
}

type ObjectState

type ObjectState string
const (
	ObjectStateDraft             ObjectState = "draft"
	ObjectStateApproved          ObjectState = "approved"
	ObjectStateApprovedWithDraft ObjectState = "approvedWithDraft"
)

type ObjectVersion

type ObjectVersion string
const (
	DraftVersion    ObjectVersion = "draft"
	ApprovedVersion ObjectVersion = "approved"
)

type Query

type Query struct {
	FilterField   string   `json:"filterType,omitempty"`
	FilterValues  []string `json:"filterValues,omitempty"`
	Fields        []string `json:"fields,omitempty"`
	BatchSize     int      `json:"batchSize,omitempty"`
	NextPageToken string   `json:"nextPageToken,omitempty"`
}

Query contains the possible parameters used when listing Marketo objects

func (*Query) Values

func (q *Query) Values() (url.Values, error)

Values returns the query payload as url.Values; if the query is invalid, an error is returned.

type QueryOption

type QueryOption func(*Query)

QueryOption defines the signature of functional options for Marketo Query APIs.

func FilterField

func FilterField(field string) QueryOption

FilterField sets the field to search Marketo using

func FilterValues

func FilterValues(values []string) QueryOption

FilterValues sets the possible values to match

func GetFields

func GetFields(fields ...string) QueryOption

GetFields sets the fields to retrieve for matching records

func GetPage

func GetPage(t string) QueryOption

GetPage sets the paging token for the query

type Reason

type Reason struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

A Reason is provided along with errors, warnings, and some operations

func (Reason) Error

func (r Reason) Error() string

type RecordResult

type RecordResult struct {
	ID      int      `json:"id"`
	Status  string   `json:"status"`
	Reasons []Reason `json:"reasons,omitempty"`
}

RecordResult holds Marketo record-level result

type RelatedObject

type RelatedObject struct {
	Field string `json:"field"`
	Name  string `json:"name"`
}

type Response

type Response struct {
	RequestID     string          `json:"requestId"`
	Success       bool            `json:"success"`
	NextPageToken string          `json:"nextPageToken,omitempty"`
	MoreResult    bool            `json:"moreResult,omitempty"`
	Errors        []Reason        `json:"errors,omitempty"`
	Result        json.RawMessage `json:"result,omitempty"`
	Warnings      []Reason        `json:"warning,omitempty"`
}

Response is the common Marketo response which covers most of the Marketo response format

type TokenInfo

type TokenInfo struct {
	// Token is the currently active token.
	Token string
	// Expires shows what time the token expires
	Expires time.Time
}

TokenInfo holds authentication token and time at which expires.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL