diff --git a/README.md b/README.md index c9466ae..9832a00 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,12 @@ Official Documentation: [VisitorActivities](http://developer.pardot.com/kb/api-v - Query - Read +### Visits +Official Documentation: [Visits](https://developer.pardot.com/kb/api-version-3/visits/) + +- Query +- Read + ## How to Contribute Want to help implement the missing API end points? Fork the repository, write some code, and diff --git a/src/main/java/com/darksci/pardot/api/PardotClient.java b/src/main/java/com/darksci/pardot/api/PardotClient.java index ff8ef7b..759d903 100644 --- a/src/main/java/com/darksci/pardot/api/PardotClient.java +++ b/src/main/java/com/darksci/pardot/api/PardotClient.java @@ -58,6 +58,8 @@ import com.darksci.pardot.api.parser.user.UserCreateResponseParser; import com.darksci.pardot.api.parser.user.UserQueryResponseParser; import com.darksci.pardot.api.parser.user.UserReadResponseParser; +import com.darksci.pardot.api.parser.visit.VisitQueryResponseParser; +import com.darksci.pardot.api.parser.visit.VisitReadResponseParser; import com.darksci.pardot.api.parser.visitor.VisitorQueryResponseParser; import com.darksci.pardot.api.parser.visitor.VisitorReadResponseParser; import com.darksci.pardot.api.parser.visitoractivity.VisitorActivityQueryResponseParser; @@ -127,6 +129,8 @@ import com.darksci.pardot.api.request.user.UserQueryRequest; import com.darksci.pardot.api.request.user.UserReadRequest; import com.darksci.pardot.api.request.user.UserUpdateRoleRequest; +import com.darksci.pardot.api.request.visit.VisitQueryRequest; +import com.darksci.pardot.api.request.visit.VisitReadRequest; import com.darksci.pardot.api.request.visitor.VisitorAssignRequest; import com.darksci.pardot.api.request.visitor.VisitorQueryRequest; import com.darksci.pardot.api.request.visitor.VisitorReadRequest; @@ -170,6 +174,8 @@ import com.darksci.pardot.api.response.user.User; import com.darksci.pardot.api.response.user.UserAbilitiesResponse; import com.darksci.pardot.api.response.user.UserQueryResponse; +import com.darksci.pardot.api.response.visit.Visit; +import com.darksci.pardot.api.response.visit.VisitQueryResponse; import com.darksci.pardot.api.response.visitor.Visitor; import com.darksci.pardot.api.response.visitor.VisitorQueryResponse; import com.darksci.pardot.api.response.visitoractivity.VisitorActivity; @@ -1127,6 +1133,28 @@ public Optional visitorActivityRead(final VisitorActivityReadRe ); } + /** + * Make API request to query visits. + * @param request Request definition. + * @return Parsed api response. + */ + public VisitQueryResponse.Result visitQuery(final VisitQueryRequest request) { + return submitRequest(request, new VisitQueryResponseParser()) + .orElseThrowInvalidRequestException(); + } + + /** + * Make API request to read a visit. + * @param request Request definition. + * @return Parsed api response + */ + public Optional visitRead(final VisitReadRequest request) { + return optionalUnlessErrorCode( + submitRequest(request, new VisitReadResponseParser()), + ErrorCode.INVALID_ID, ErrorCode.INVALID_VISIT_ID + ); + } + /** * Entry point for adhoc user defined requests. * diff --git a/src/main/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParser.java b/src/main/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParser.java new file mode 100644 index 0000000..14a92cf --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParser.java @@ -0,0 +1,35 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.parser.visit; + +import com.darksci.pardot.api.parser.JacksonFactory; +import com.darksci.pardot.api.parser.ResponseParser; +import com.darksci.pardot.api.response.visit.VisitQueryResponse; + +import java.io.IOException; + +/** + * Handles parsing Visit Query API responses into POJOs. + */ +public class VisitQueryResponseParser implements ResponseParser { + + @Override + public VisitQueryResponse.Result parseResponse(final String responseStr) throws IOException { + return JacksonFactory.newInstance().readValue(responseStr, VisitQueryResponse.class).getResult(); + } +} diff --git a/src/main/java/com/darksci/pardot/api/parser/visit/VisitReadResponseParser.java b/src/main/java/com/darksci/pardot/api/parser/visit/VisitReadResponseParser.java new file mode 100644 index 0000000..ac27d1a --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/parser/visit/VisitReadResponseParser.java @@ -0,0 +1,36 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.parser.visit; + +import com.darksci.pardot.api.parser.JacksonFactory; +import com.darksci.pardot.api.parser.ResponseParser; +import com.darksci.pardot.api.response.visit.Visit; +import com.darksci.pardot.api.response.visit.VisitReadResponse; + +import java.io.IOException; + +/** + * Handles parsing Visit Read API responses into POJOs. + */ +public class VisitReadResponseParser implements ResponseParser { + + @Override + public Visit parseResponse(final String responseStr) throws IOException { + return JacksonFactory.newInstance().readValue(responseStr, VisitReadResponse.class).getVisit(); + } +} diff --git a/src/main/java/com/darksci/pardot/api/request/visit/VisitQueryRequest.java b/src/main/java/com/darksci/pardot/api/request/visit/VisitQueryRequest.java new file mode 100644 index 0000000..e31bce0 --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/request/visit/VisitQueryRequest.java @@ -0,0 +1,91 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.request.visit; + +import com.darksci.pardot.api.request.BaseQueryRequest; + +import java.util.Collection; + +/** + * Defines a Visit Query Request. + */ +public class VisitQueryRequest extends BaseQueryRequest { + + @Override + public String getApiEndpoint() { + return "visit/do/query"; + } + + // Filter Options + + /** + * Only select visits who are associated with the specified visit id. + * @param id The visit id to filter by. + * @return RequestBuilder + */ + public VisitQueryRequest withId(final Long id) { + return withCollectionParam("ids", id); + } + + /** + * Only select visits who are associated with the specified visit ids. + * @param ids The visit ids to filter by. + * @return RequestBuilder + */ + public VisitQueryRequest withIds(final Collection ids) { + return withCollectionParams("ids", ids); + } + + /** + * Only select visits who are associated with the specified visitor id. + * @param visitorId The visitor id to filter by. + * @return RequestBuilder + */ + public VisitQueryRequest withVisitorId(final Long visitorId) { + return withCollectionParam("visitor_ids", visitorId); + } + + /** + * Only select visits who are associated with the specified visitor ids. + * @param visitorIds The visitor ids to filter by. + * @return RequestBuilder + */ + public VisitQueryRequest withVisitorIds(final Collection visitorIds) { + return withCollectionParams("visitor_ids", visitorIds); + } + + /** + * Only select visits who are associated with the specified prospect id. + * @param prospectId The prospect id to filter by. + * @return RequestBuilder + */ + public VisitQueryRequest withProspectId(final Long prospectId) { + return withCollectionParam("prospect_ids", prospectId); + } + + /** + * Only select visits who are associated with the specified prospect ids. + * @param prospectIds The prospect ids to filter by. + * @return RequestBuilder + */ + public VisitQueryRequest withProspectIds(final Collection prospectIds) { + return withCollectionParams("prospect_ids", prospectIds); + } + + +} diff --git a/src/main/java/com/darksci/pardot/api/request/visit/VisitReadRequest.java b/src/main/java/com/darksci/pardot/api/request/visit/VisitReadRequest.java new file mode 100644 index 0000000..0f61c35 --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/request/visit/VisitReadRequest.java @@ -0,0 +1,40 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.request.visit; + +import com.darksci.pardot.api.request.BaseRequest; + +/** + * Used to generate a Visit read request. + */ +public class VisitReadRequest extends BaseRequest { + + @Override + public String getApiEndpoint() { + return "visit/do/read"; + } + + /** + * Returns the data for the visit specified by id. + * @param id The Id of the target visit. + * @return VisitReadRequest builder. + */ + public VisitReadRequest selectById(final Long id) { + return setParam("id", id); + } +} diff --git a/src/main/java/com/darksci/pardot/api/response/ErrorCode.java b/src/main/java/com/darksci/pardot/api/response/ErrorCode.java index f83f948..32be61a 100644 --- a/src/main/java/com/darksci/pardot/api/response/ErrorCode.java +++ b/src/main/java/com/darksci/pardot/api/response/ErrorCode.java @@ -37,6 +37,7 @@ public enum ErrorCode { INVALID_VISITOR_ID(24), INVALID_OPPORTUNITY_ID(35), INVALID_CAMPAIGN_ID(38), + INVALID_VISIT_ID(48), EMAIL_ADDRESS_IS_ALREADY_IN_USE(54), INVALID_LIST_ID(55), INVALID_EMAIL_FORMAT(65), diff --git a/src/main/java/com/darksci/pardot/api/response/visit/Visit.java b/src/main/java/com/darksci/pardot/api/response/visit/Visit.java new file mode 100644 index 0000000..ae4bbcb --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/response/visit/Visit.java @@ -0,0 +1,112 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.response.visit; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import org.joda.time.LocalDateTime; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a Pardot visit. + */ +public class Visit { + private Long id; + private Long visitorId; + private Long prospectId; + private Integer visitorPageViewCount; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime firstVisitorPageViewAt; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime lastVisitorPageViewAt; + private Integer durationInSeconds; + private String campaignParameter; + private String mediumParameter; + private String sourceParameter; + private String contentParameter; + private String termParameter; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdAt; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updatedAt; + + @JacksonXmlElementWrapper(localName = "visitor_page_views") + private List visitorPageViews; + + public Long getId() { return id; } + + public Long getVisitorId() { return visitorId; } + + public Long getProspectId() { return prospectId; } + + public Integer getVisitorPageViewCount() { return visitorPageViewCount; } + + public LocalDateTime getFirstVisitorPageViewAt() { return firstVisitorPageViewAt; } + + public LocalDateTime getLastVisitorPageViewAt() { return lastVisitorPageViewAt; } + + public Integer getDurationInSeconds() { return durationInSeconds; } + + public String getCampaignParameter() { return campaignParameter; } + + public String getMediumParameter() { return mediumParameter; } + + public String getSourceParameter() { return sourceParameter; } + + public String getContentParameter() { return contentParameter; } + + public String getTermParameter() { return termParameter; } + + public LocalDateTime getCreatedAt() { return createdAt; } + + public LocalDateTime getUpdatedAt() { return updatedAt; } + + /** + * Visitor Page Views associated to the visit, or empty list if none. + * + * @return Associated Visitor Page Views, or empty list if none. + */ + public List getVisitorPageViews() { + if (visitorPageViews == null) { + return new ArrayList<>(); + } + return visitorPageViews; + } + + @Override + public String toString() { + return "Visitor{" + + "id=" + id + + ", visitorId=" + visitorId + + ", prospectId=" + prospectId + + ", visitorPageViewCount=" + visitorPageViewCount + + ", firstVisitorPageViewAt=" + firstVisitorPageViewAt + + ", lastVisitorPageViewAt=" + lastVisitorPageViewAt + + ", durationInSeconds=" + durationInSeconds + + ", campaignParameter='" + campaignParameter + '\'' + + ", mediumParameter='" + mediumParameter + '\'' + + ", sourceParameter='" + sourceParameter + '\'' + + ", contentParameter='" + contentParameter + '\'' + + ", termParameter='" + termParameter + '\'' + + ", createdAt=" + createdAt + + ", updatedAt=" + updatedAt + + '}'; + } +} diff --git a/src/main/java/com/darksci/pardot/api/response/visit/VisitQueryResponse.java b/src/main/java/com/darksci/pardot/api/response/visit/VisitQueryResponse.java new file mode 100644 index 0000000..5806ade --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/response/visit/VisitQueryResponse.java @@ -0,0 +1,75 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.response.visit; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +import java.util.Collections; +import java.util.List; + +/** + * Represents the result from a Visit Query API call. + */ +public class VisitQueryResponse { + private Result result; + + public Result getResult() { + return result; + } + + /** + * Represents one or more visitors. + */ + public static class Result { + private Integer totalResults = 0; + + @JacksonXmlProperty(localName = "visit") + private List visits = Collections.emptyList(); + + public Integer getTotalResults() { + return totalResults; + } + + /** + * Visits returned by the API. + * + * @return Visit results. + */ + public List getVisits() { + if (visits == null) { + visits = Collections.emptyList(); + } + return Collections.unmodifiableList(visits); + } + + @Override + public String toString() { + return "Result{" + + "totalResults=" + totalResults + + ", visits=" + visits + + '}'; + } + } + + @Override + public String toString() { + return "VisitQueryResponse{" + + "result=" + result + + '}'; + } +} diff --git a/src/main/java/com/darksci/pardot/api/response/visit/VisitReadResponse.java b/src/main/java/com/darksci/pardot/api/response/visit/VisitReadResponse.java new file mode 100644 index 0000000..ec14f18 --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/response/visit/VisitReadResponse.java @@ -0,0 +1,28 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.response.visit; + +/** + * Represents a Pardot Visit. + */ +public class VisitReadResponse { + + private Visit visit; + + public Visit getVisit() { return visit; } +} diff --git a/src/main/java/com/darksci/pardot/api/response/visit/VisitorPageView.java b/src/main/java/com/darksci/pardot/api/response/visit/VisitorPageView.java new file mode 100644 index 0000000..4534994 --- /dev/null +++ b/src/main/java/com/darksci/pardot/api/response/visit/VisitorPageView.java @@ -0,0 +1,50 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.response.visit; + +import com.fasterxml.jackson.annotation.JsonFormat; +import org.joda.time.LocalDateTime; + +/** + * Represents Visitor Page View on a Pardot Visit. + */ +public class VisitorPageView { + private Long id; + private String url; + private String title; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdAt; + + public Long getId() { return id; } + + public String getUrl() { return url; } + + public String getTitle() { return title; } + + public LocalDateTime getCreatedAt() { return createdAt; } + + @Override + public String toString() { + return "VisitorPageView{" + + "id=" + id + + ", replyToAddress='" + url + '\'' + + ", sendFromData='" + title + '\'' + + ", createdAt=" + createdAt + + '}'; + } +} diff --git a/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java b/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java index bce6a04..adb97fd 100644 --- a/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java +++ b/src/test/java/com/darksci/pardot/api/AbstractPardotClientIntegrationTest.java @@ -77,6 +77,8 @@ import com.darksci.pardot.api.request.user.UserQueryRequest; import com.darksci.pardot.api.request.user.UserReadRequest; import com.darksci.pardot.api.request.user.UserUpdateRoleRequest; +import com.darksci.pardot.api.request.visit.VisitQueryRequest; +import com.darksci.pardot.api.request.visit.VisitReadRequest; import com.darksci.pardot.api.request.visitor.VisitorAssignRequest; import com.darksci.pardot.api.request.visitor.VisitorQueryRequest; import com.darksci.pardot.api.request.visitor.VisitorReadRequest; @@ -116,6 +118,8 @@ import com.darksci.pardot.api.response.user.User; import com.darksci.pardot.api.response.user.UserAbilitiesResponse; import com.darksci.pardot.api.response.user.UserQueryResponse; +import com.darksci.pardot.api.response.visit.Visit; +import com.darksci.pardot.api.response.visit.VisitQueryResponse; import com.darksci.pardot.api.response.visitor.Visitor; import com.darksci.pardot.api.response.visitor.VisitorQueryResponse; import com.darksci.pardot.api.response.visitoractivity.VisitorActivity; @@ -1387,4 +1391,28 @@ public void visitorActivityReadTest() { assertNotNull("Should not be null", response); logger.info("Response: {}", response); } + + /** + * Test Querying visits. + */ + public void visitQueryTest() { + final long visitId = 1L; + final VisitQueryRequest request = new VisitQueryRequest().withId(visitId); + + final VisitQueryResponse.Result response = client.visitQuery(request); + assertNotNull("Should not be null", response); + logger.info("Response: {}", response); + } + + /** + * Test Reading a visit. + */ + public void visitReadTest() { + final long visitId = 1L; + final VisitReadRequest request = new VisitReadRequest().selectById(visitId); + + final Optional response = client.visitRead(request); + assertNotNull("Should not be null", response); + logger.info("Response: {}", response); + } } diff --git a/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java b/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java index a0d5695..b1e47d5 100644 --- a/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java +++ b/src/test/java/com/darksci/pardot/api/PardotClientIntegrationTest.java @@ -539,4 +539,16 @@ public void visitorActivityQueryTest() { public void visitorActivityReadTest() { super.visitorActivityReadTest(); } + + @Test + @Override + public void visitQueryTest() { + super.visitQueryTest(); + } + + @Test + @Override + public void visitReadTest() { + super.visitReadTest(); + } } \ No newline at end of file diff --git a/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java b/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java index 9d53af6..7173dd8 100644 --- a/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java +++ b/src/test/java/com/darksci/pardot/api/PardotClientSsoIntegrationTest.java @@ -547,4 +547,12 @@ public void visitorActivityQueryTest() { public void visitorActivityReadTest() { super.visitorActivityReadTest(); } + + @Test + @Override + public void visitQueryTest() { super.visitQueryTest(); } + + @Test + @Override + public void visitReadTest() { super.visitReadTest(); } } diff --git a/src/test/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParserTest.java b/src/test/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParserTest.java new file mode 100644 index 0000000..39a5e46 --- /dev/null +++ b/src/test/java/com/darksci/pardot/api/parser/visit/VisitQueryResponseParserTest.java @@ -0,0 +1,83 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.parser.visit; + +import com.darksci.pardot.api.parser.BaseResponseParserTest; +import com.darksci.pardot.api.response.visit.Visit; +import com.darksci.pardot.api.response.visit.VisitQueryResponse; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class VisitQueryResponseParserTest extends BaseResponseParserTest { + private static final Logger logger = LoggerFactory.getLogger(VisitQueryResponseParserTest.class); + + /** + * Validates we can parse a Visit query with multiple visitors response A-OK. + */ + @Test + public void testMultpleVisits() throws IOException { + final String input = readFile("visitQuery.xml"); + final VisitQueryResponse.Result response = new VisitQueryResponseParser().parseResponse(input); + logger.info("Result: {}", response); + + assertNotNull("Should not be null", response); + assertEquals("Should have 2 results", 2, (int) response.getTotalResults()); + assertEquals("Should have 2 results", 2, response.getVisits().size()); + validateVisit1(response.getVisits().get(0)); + validateVisit2(response.getVisits().get(1)); + } + + private void validateVisit1(final Visit visit) { + assertEquals("Has correct id", 37640L, (long) visit.getId()); + assertEquals("Has correct visitorId", 123L, (long) visit.getVisitorId()); + assertEquals("Has correct prospectId", 123L, (long) visit.getProspectId()); + assertEquals("Has correct visitorPageViewCount", 1024, (int) visit.getVisitorPageViewCount()); + assertEquals("Has correct firstVisitorPageViewAt", "2015-09-03T11:57:01.000", visit.getFirstVisitorPageViewAt().toString()); + assertEquals("Has correct lastVisitorPageViewAt", "2015-09-03T11:57:24.000", visit.getLastVisitorPageViewAt().toString()); + assertEquals("Has correct durationInSeconds", 1024, (int) visit.getDurationInSeconds()); + assertEquals("Has correct campaign parameter", "Campaign Parameter", visit.getCampaignParameter()); + assertEquals("Has correct medium parameter", "Medium Parameter", visit.getMediumParameter()); + assertEquals("Has correct Source parameter", "Source Parameter", visit.getSourceParameter()); + assertEquals("Has correct Content parameter", "Content Parameter", visit.getContentParameter()); + assertEquals("Has correct Term parameter", "Term Parameter", visit.getTermParameter()); + assertEquals("Has correct createdAt", "2015-09-03T11:57:01.000", visit.getCreatedAt().toString()); + assertEquals("Has correct updatedAt", "2015-09-03T11:57:24.000", visit.getUpdatedAt().toString()); + } + + private void validateVisit2(final Visit visit) { + assertEquals("Has correct id", 37641L, (long) visit.getId()); + assertNull("Field is null", visit.getVisitorId()); + assertNull("Field is null", visit.getProspectId()); + assertNull("Field is null", visit.getVisitorPageViewCount()); + assertNull("Field is null", visit.getFirstVisitorPageViewAt()); + assertNull("Field is null", visit.getLastVisitorPageViewAt()); + assertNull("Field is null", visit.getDurationInSeconds()); + assertNull("Field is null", visit.getCampaignParameter()); + assertNull("Field is null", visit.getMediumParameter()); + assertNull("Field is null", visit.getSourceParameter()); + assertNull("Field is null", visit.getContentParameter()); + assertNull("Field is null", visit.getTermParameter()); + assertEquals("Has correct createdAt", "2015-10-03T11:57:01.000", visit.getCreatedAt().toString()); + assertEquals("Has correct updatedAt", "2015-10-03T11:57:24.000", visit.getUpdatedAt().toString()); + } +} \ No newline at end of file diff --git a/src/test/java/com/darksci/pardot/api/parser/visit/VisitReadResponseResponseParserTest.java b/src/test/java/com/darksci/pardot/api/parser/visit/VisitReadResponseResponseParserTest.java new file mode 100644 index 0000000..6507326 --- /dev/null +++ b/src/test/java/com/darksci/pardot/api/parser/visit/VisitReadResponseResponseParserTest.java @@ -0,0 +1,64 @@ +/** + * Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.darksci.pardot.api.parser.visit; + +import com.darksci.pardot.api.parser.BaseResponseParserTest; +import com.darksci.pardot.api.response.visit.Visit; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class VisitReadResponseResponseParserTest extends BaseResponseParserTest { + private static final Logger logger = LoggerFactory.getLogger(VisitReadResponseResponseParserTest.class); + + /** + * Validates we can parse a Visit Read + */ + @Test + public void testRead() throws IOException { + final String input = readFile("visitRead.xml"); + final Visit visit = new VisitReadResponseParser().parseResponse(input); + logger.info("Result: {}", visit); + + assertNotNull("Has non null response", visit); + validateVisit1(visit); + } + + private void validateVisit1(final Visit visit) { + assertEquals("Has correct id", 37640L, (long) visit.getId()); + assertEquals("Has correct visitorId", 123L, (long) visit.getVisitorId()); + assertEquals("Has correct prospectId", 123L, (long) visit.getProspectId()); + assertEquals("Has correct visitorPageViewCount", 1024, (int) visit.getVisitorPageViewCount()); + assertEquals("Has correct firstVisitorPageViewAt", "2015-09-03T11:57:01.000", visit.getFirstVisitorPageViewAt().toString()); + assertEquals("Has correct lastVisitorPageViewAt", "2015-09-03T11:57:24.000", visit.getLastVisitorPageViewAt().toString()); + assertEquals("Has correct durationInSeconds", 1024, (int) visit.getDurationInSeconds()); + assertEquals("Has correct campaign parameter", "Campaign Parameter", visit.getCampaignParameter()); + assertEquals("Has correct medium parameter", "Medium Parameter", visit.getMediumParameter()); + assertEquals("Has correct Source parameter", "Source Parameter", visit.getSourceParameter()); + assertEquals("Has correct Content parameter", "Content Parameter", visit.getContentParameter()); + assertEquals("Has correct Term parameter", "Term Parameter", visit.getTermParameter()); + assertEquals("Has correct createdAt", "2015-09-03T11:57:01.000", visit.getCreatedAt().toString()); + assertEquals("Has correct updatedAt", "2015-09-03T11:57:24.000", visit.getUpdatedAt().toString()); + assertFalse("Should NOT have empty visitor page view list", visit.getVisitorPageViews().isEmpty()); + assertEquals("Should have 2 visitor page views", 2, visit.getVisitorPageViews().size()); + } +} \ No newline at end of file diff --git a/src/test/resources/mockResponses/visitQuery.xml b/src/test/resources/mockResponses/visitQuery.xml new file mode 100644 index 0000000..95befe3 --- /dev/null +++ b/src/test/resources/mockResponses/visitQuery.xml @@ -0,0 +1,38 @@ + + + + 2 + + 37640 + 123 + 123 + 1024 + 2015-09-03 11:57:01 + 2015-09-03 11:57:24 + 1024 + Campaign Parameter + Medium Parameter + Source Parameter + Content Parameter + Term Parameter + 2015-09-03 11:57:01 + 2015-09-03 11:57:24 + + + 37641 + + + + + + + + + + + + 2015-10-03 11:57:01 + 2015-10-03 11:57:24 + + + \ No newline at end of file diff --git a/src/test/resources/mockResponses/visitRead.xml b/src/test/resources/mockResponses/visitRead.xml new file mode 100644 index 0000000..d33850e --- /dev/null +++ b/src/test/resources/mockResponses/visitRead.xml @@ -0,0 +1,33 @@ + + + + 37640 + 123 + 123 + 1024 + 2015-09-03 11:57:01 + 2015-09-03 11:57:24 + 1024 + Campaign Parameter + Medium Parameter + Source Parameter + Content Parameter + Term Parameter + 2015-09-03 11:57:01 + 2015-09-03 11:57:24 + + + 111 + http://go.pardot.com/l/1/2016-06-03/2khmg8 + title1 + 2015-09-03 11:57:01 + + + 222 + http://go.pardot.com/l/1/2016-06-03/2khmg8 + title2 + 2015-09-03 11:57:01 + + + + \ No newline at end of file