A Ruby interface to the Wix Hive API.
- Prerequisites
- Installation
- Quick Start
- Manual
- Configuration
- Hive DTOs
- Hive Cursored Data
- Hive Errors
- Contacts API
- Concurrency Control
- client.new_contact
- client.contact
- client.update_contact (PENDING)
- client.contacts_tags (PENDING)
- client.contacts_subscribers (PENDING)
- client.update_contact_name
- client.update_contact_company
- client.update_contact_picture
- client.update_contact_address
- client.update_contact_email
- client.update_contact_phone
- client.update_contact_date
- client.update_contact_note (PENDING)
- client.update_contact_custom (PENDING)
- client.add_contact_address
- client.add_contact_email
- client.add_contact_phone
- client.add_contact_note
- client.add_contact_custom
- client.add_contact_tags (PENDING)
- client.add_contact_activity
- client.contact_activities
- client.contacts
- client.upsert_contact
- Activities API
- Insights API
- Sites API
- Redirects API
- Contributing
- Read about developing a third party app for the Wix platform.
- Register your app here to obtain your APP_ID and APP_SECRET
Add this line to your application's Gemfile:
gem 'wix-hive-ruby'
And then execute:
$ bundle
Or install it yourself as:
$ gem install wix-hive-ruby
require 'sinatra'
require 'wix-hive-ruby'
SECRET_KEY = 'YOUR_SECRET_KEY'
APP_ID = 'YOUR_APP_ID'
# The route should match the app endpoint set during registration
get '/' do
# The GET request to your app endpoint will contain an instance parameter for you to parse
instance = params.delete('instance')
# Parse the instance parameter
wixInstance = Hive::Client.parse_instance_data(instance, SECRET_KEY)
# Create a Wix Hive Client
client = Hive::Client.new do |config|
config.secret_key = SECRET_KEY
config.app_id = APP_ID
config.instance_id = wixInstance.instanceId
end
contact = Hive::Contact.new
contact.name.first = 'Quick'
contact.name.last = 'Start'
contact.add_email(email: 'quick.start@example.com', tag: 'work')
contact.add_phone(phone: '123456789', tag: 'work')
contact.add_url(url: 'wix.com', tag: 'site')
# Create a new contact
contact_res = client.new_contact(contact)
FACTORY = Hive::Activities
activity = Hive::Activity.new(
type: FACTORY::MUSIC_ALBUM_FAN.type,
locationUrl: 'http://www.wix.com',
details: { summary: 'test', additionalInfoUrl: 'http://www.wix.com' },
info: { album: { name: 'Wix', id: '1234' } })
# Add an activity to the contact
activity_res = client.add_contact_activity(contact_res.contactId, activity)
body "Contact created: #{contact_res.contactId}.
Activity created: #{activity_res.activityId}
Thank you!"
end
after do
headers({ 'X-Frame-Options' => 'ALLOW-FROM wix.com' })
end
The entry point to the Wix Hive API is the Hive::Client
. You can initialize the class by passing it a configuration block.
####The basic configuration is:
Hive::Client.new do |config|
config.secret_key = 'SECRET-KEY'
config.app_id = 'APP-ID'
config.instance_id = 'INSTANCE-ID'
end
- The
config.secret_key
andconfig.app_id
are obtained by registering an app as it is outlined here - The
config.instance_id
is obtained by decoding the signed app instance. Learn more about this here- Note: The Hive client has a utility method that parses the instance data. Example usage:
wixInstance = Hive::Client.parse_instance_data(INSTANCE, SECRET-KEY) wixInstance.demoMode wixInstance.instanceId wixInstance.ipAndPort wixInstance.permissions wixInstance.signDate wixInstance.uid wixInstance.vendorProductId
####Advanced configuration options include:
config.logger
options::stdout
logs the request and response data to the STDOUT.:file
logs the request and response data to hive.log.
config.request_config
appends items to the default Faraday request configuration.- Example:
config.request_config = { open_timeout: 10, timeout: 30 }
config.headers
appends items to the default request headers.- Example:
config.headers = { custom-header: 'custom' }
config.api_family
global api family version defaults tov1
.config.api_version
global api version defaults to1.0.0
.config.api_base
global api version defaults tohttps://openapi.wix.com
.
The Hive DTOs are based on Hashie which in essence means that they are hashes with extra functionality.
####Constructing request data
#####There are two ways of doing it:
- The "OO way" which is basically creating objects and composing them together.
- Example:
contact = Hive::Contact.new
contact.name.first = 'E2E'
contact.name.last = 'Cool'
contact.company.name = 'Wix'
contact.company.role = 'CEO'
contact.add_email(email: 'alext@wix.com', tag: 'work')
contact.add_phone(phone: '123456789', tag: 'work')
contact.add_address(tag: 'home', address: '28208 N Inca St.', neighborhood: 'LODO', city: 'Denver', region: 'CO', country: 'US', postalCode: '80202')
contact.add_date(date: Time.now.iso8601(3), tag: 'E2E')
contact.add_url(url: 'wix.com', tag: 'site')
- The "dynamic way" which means creating hashes and wiring them together. (Note: these will be transformed to objects 'under the hood'.)
- Example:
guest = { total: 1, adults: 1, children: 0 }
day_ago = (Time.now - (60 * 60 * 24)).iso8601(3)
stay = { checkin: day_ago, checkout: Time.now.iso8601(3) }
invoice = {total: '1', subtotal: '1', currency: 'EUR'}
payment = {total: '1', subtotal: '1', currency: 'EUR', source: 'Cash'}
activity = Hive::Activity.new(
type: FACTORY::HOTELS_PURCHASE.type,
locationUrl: 'http://www.wix.com',
details: {summary: 'test', additionalInfoUrl: 'http://www.wix.com'},
info: { source: 'GUEST', guests: guest, stay: stay, invoice: invoice, payment: payment })
###Accessing response data
The response JSON is transformed into a DTO object. And can be accessed as shown in the example below:
- Example JSON response:
{
"createdAt": "2014-09-02T04:57:43.081-05:00",
"emails": [
{
"contactSubscriptionStatus": "notSet",
"email": "alext@wix.com",
"emailStatus": "transactional",
"id": 1,
"siteOwnerSubscriptionStatus": "notSet",
"tag": "work"
}
],
"id": "9e2c4236-2b81-4800-b7bd-d0365c9a391e",
"name": {
"first": "Wix",
"last": "Cool",
"middle": "",
"prefix": "",
"suffix": ""
},
"notes": [],
"phones": [
{
"id": 1,
"phone": "123456789",
"tag": "work"
}
],
"tags": [
"contacts/create",
"contacts_server/new",
"contacts_server/show"
],
"urls": []
}
- Example accessing data:
contact.id # "9e2c4236-2b81-4800-b7bd-d0365c9a391e"
contact.createdAt # "2014-09-02T04:57:43.081-05:00"
contact.name.first # "Wix"
contact.name.last # "Cool"
contact.phones.first.id # 1
contact.phones.first.phone # 123456789
contact.phones.first.tag # work
contact.tags.first # "contacts/create"
contact.emails.first.email # "alext@wix.com"
A cursored response JSON looks like:
{
"nextCursor": "fd14d5ef831fb9d2e43da26b2c8fe74b704d3fd9ab8be9a251540ecea236f28fa532c035b4ca796387ab114aa37fef098b5cddf114fca450f8868b27e3393299",
"pageSize": 25,
"results": [......],
"total": 1749
}
That gets mapped to a Hive::Cursor
object and can be accessed in the same way as the DTOs.(Note: the results objects are also transformed to DTOs)
Here is a list of methods that the cursor object contains:
.next?
.previous?
.next_page
.previous_page
400 => Hive::Response::Error::BadRequest,
403 => Hive::Response::Error::Forbidden,
404 => Hive::Response::Error::NotFound,
408 => Hive::Response::Error::RequestTimeout,
429 => Hive::Response::Error::TooManyRequests,
500 => Hive::Response::Error::InternalServerError,
502 => Hive::Response::Error::BadGateway,
503 => Hive::Response::Error::ServiceUnavailable,
504 => Hive::Response::Error::GatewayTimeout
Hive::CursorOperationError
Hive::ConfigurationError
Hive::SignatureError
The contacts add and update methods have a concurrency control mechanism associated with them. The mechanism is based on the modifiedAt
request parameter. This parameter needs to have the same value as the underlying contact that is being updated.
For example: let us assume we have a contact with id=1
and modifiedAt=2014-10-01T14:43:48.560+03:00
and we want to update the email field. What we would need to do is execute the following method:
new_email = Hive::Email.new
new_email.tag = 'work_new'
new_email.email = 'alex_new@example.com'
new_email.emailStatus = 'optOut'
client.add_contact_email('1', new_email, '2014-10-01T14:43:48.560+03:00')
So lets think about the concurrency now. Let assume we have two update email requests that come in the same time and they get processed sequentially. First one would get processed and update the contact email and in the same time the contacts’ modifiedAt
will change. Second request gets processed but it will fail with a concurrency validation error because it is trying to perform an update operation on a old version of the contact object. And the system knows that by comparing the two modifiedAt
parameters (one from the DB and the one provided).
Example:
contact = Hive::Contact.new
contact.name.first = 'E2E'
contact.name.last = 'Cool'
contact.company.name = 'Wix'
contact.company.role = 'CEO'
contact.add_email(email: 'alext@wix.com', tag: 'work')
contact.add_phone(phone: '123456789', tag: 'work')
contact.add_address(tag: 'home', address: '28208 N Inca St.', neighborhood: 'LODO', city: 'Denver', region: 'CO', country: 'US', postalCode: '80202')
contact.add_date(date: Time.now.iso8601(3), tag: 'E2E')
contact.add_url(url: 'wix.com', tag: 'site')
# PENDING
# contact.add_note(content: 'alex', modifiedAt: '2014-08-05T13:59:37.873Z')
# contact.add_custom(field: 'custom1', value: 'custom')
client.new_contact(contact)
Get a Contact by ID
Example:
contact = client.contact(CONTACT_ID)
Example:
contact.add_email(email: 'wow@wix.com', tag: 'wow')
contact.add_address(tag: 'home2', address: '1625 Larimer', neighborhood: 'LODO', city: 'Denver', region: 'CO', country: 'US', postalCode: '80202')
contact.add_date(date: Time.now.iso8601(3), tag: 'E2E UPDATE')
contact.add_url(url: 'wix.com', tag: 'site')
# PENDING
client.update_contact(CONTACT_ID, contact, MODIFIED_AT)
Example:
client.contacts_tags
Example:
client.contacts_subscribers
Example:
client.update_contact_name(CONTACT_ID, Hive::Name.new(first: 'New_Name'), MODIFIED_AT)
Example:
company = Hive::Company.new
company.name = 'New_Company'
client.update_contact_company(CONTACT_ID, company, MODIFIED_AT)
Example:
client.update_contact_picture(CONTACT_ID, 'wix.com/example.jpg', MODIFIED_AT)
Example:
updated_address = Hive::Address.new
updated_address.tag = 'work'
updated_address.address = '1625 Larimer St.'
client.update_contact_address(CONTACT_ID, ADDRESS_ID, updated_address, MODIFIED_AT)
Example:
updated_email = Hive::Email.new
updated_email.tag = 'work'
updated_email.email = 'alex@example.com'
updated_email.emailStatus = 'optOut'
client.update_contact_email(CONTACT_ID, EMAIL_ID, updated_email, MODIFIED_AT)
Example:
updated_phone = Hive::Phone.new
updated_phone.tag = 'work'
updated_phone.phone = '18006666'
client.update_contact_phone(CONTACT_ID, PHONE_ID, updated_phone, MODIFIED_AT)
Example:
date = Hive::Date.new
date.date = Time.now.iso8601(3)
date.tag = 'update'
client.update_contact_date(CONTACT_ID, DATE_ID, date, MODIFIED_AT)
Example:
note = Hive::Note.new
note.content = 'Note'
note.modifiedAt = Time.now.iso8601(3)
client.update_contact_phone(CONTACT_ID, NOTE_ID, note, MODIFIED_AT)
Example:
custom = Hive::Custom.new
custom.field = 'custom_update'
custom.value = 'custom_value'
client.update_contact_phone(CONTACT_ID, CUSTOM_ID, custom, MODIFIED_AT)
Example:
new_address = Hive::Address.new
new_address.tag = 'work'
new_address.address = '1625 Larimer St.'
client.add_contact_address(CONTACT_ID, new_address, MODIFIED_AT)
Example:
new_email = Hive::Email.new
new_email.tag = 'work_new'
new_email.email = 'alex_new@example.com'
new_email.emailStatus = 'optOut'
client.add_contact_email(CONTACT_ID, new_email, MODIFIED_AT)
Example:
new_phone = Hive::Phone.new
new_phone.tag = 'work_new'
new_phone.phone = '18006666'
client.add_contact_phone(CONTACT_ID, new_phone, MODIFIED_AT)
Example:
note = Hive::Note.new
note.content = 'Note'
client.add_contact_note(CONTACT_ID, note, MODIFIED_AT)
Example:
custom = Hive::Custom.new
custom.field = 'custom_update'
custom.value = 'custom_value'
client.add_contact_custom(CONTACT_ID, custom, MODIFIED_AT)
Example:
tags = ['tag1/tag', 'tag2/tag']
client.add_contact_tags(CONTACT_ID, tags, MODIFIED_AT)
Example:
FACTORY = Hive::Activities
activity = Hive::Activity.new(
type: FACTORY::MUSIC_ALBUM_FAN.type,
locationUrl: 'http://www.wix.com',
details: { summary: 'test', additionalInfoUrl: 'http://www.wix.com' },
info: { album: { name: 'Wix', id: '1234' } })
client.add_contact_activity(CONTACT_ID, activity)
Example:
client.contact_activities(CONTACT_ID)
Examples:
client.contacts
client.contacts( pageSize: 50 )
Examples:
client.upsert_contact( phone: '123456789' )
client.upsert_contact( email: 'alex@example.com' )
client.upsert_contact( phone: '123456789', email: 'alex@example.com' )
Note: Activity info is created via a factory: 'FACTORY = Hive::Activities'
Example:
activity = Hive::Activity.new(
type: FACTORY::MUSIC_ALBUM_FAN.type,
locationUrl: 'http://www.wix.com',
details: { summary: 'test', additionalInfoUrl: 'http://www.wix.com' },
info: { album: { name: 'Wix', id: '1234' } })
client.new_activity(SESSION_ID, activity)
Example:
client.activity(ACTIVITY_ID)
Examples:
client.activities
client.activities(activityTypes: Hive::Activities::MUSIC_ALBUM_FAN.type)
client.activities(from: Time.now.iso8601(3), until: Time.now.iso8601(3))
Example:
client.activities_summary
Example:
client.contact_activities_summary(CONTACT_ID)
Example:
client.sites_site
Example:
client.sites_site_pages
Example:
client.redirects
Everyone is encouraged to help improve this gem. Some of the ways you can contribute include:
- Use alpha, beta, and pre-release versions.
- Report bugs.
- Suggest new features.
- Write or edit documentation.
- Write specifications.
- Write code (no patch is too small: fix typos, clean up inconsistent whitespace).
- Refactor code.
- Fix issues.
- Submit an Issue
We use the GitHub issue tracker to track bugs and features. Before submitting a bug report or feature request, check to make sure it hasn't already been submitted. When submitting a bug report, please include a Gist that includes a stack trace and any details that may be necessary to reproduce the bug, including your gem version, Ruby version, and operating system. Ideally, a bug report should include a pull request with failing specs.
- Fork it ( https://github.com/[my-github-username]/wix-hive-ruby/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Add specs for your unimplemented feature or bug fix. (Note: When developing a new API a
e2e
test is mandatory.) - Run
bundle exec rake spec
. If your specs pass, return to step 3. (Note: When developing a new API runbundle exec rake e2e
first. This will record a VCR Cassette the first time you run it.) - Implement your feature or bug fix.
- Run
bundle exec rake
. If your specs fail, return to step 5. (Note: Fix any rubocop issues that were not automatically fixed.) - Run open coverage/index.html. If your changes are not completely covered by your tests, return to step 3.
- Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request